import * as THREE from 'three';
import { BaseDemo } from './BaseDemo';
import { Emitter, GravityForceField, ParticleSystem, Tween } from '../index';
import { getSPEMat } from '../util';
import GUI from "three/examples/jsm/libs/lil-gui.module.min.js";

export class FlameDemo extends BaseDemo {
    private emitter?: Emitter;
    private colorTween?: Tween<THREE.Color>;
    private sizeTween?: Tween<number>;
    private upwardForce?: GravityForceField;

    constructor(scene: THREE.Scene) {
        super('火焰效果', '逼真的火焰效果，展示向上浮力、颜色渐变和尺寸变化', scene);
    }

    init(): void {
        // 创建火焰材质
        const material = getSPEMat({
            color: new THREE.Color(0xffffff),
            size: 8,
            sizeAttenuation: false,
            vertexColors: true,
            depthTest: true,
            depthWrite: false,
            blending: THREE.AdditiveBlending,
            transparent: true,
            opacity: 0.8,
        });

        // 创建发射器 - 从底部向上发射
        this.emitter = new Emitter({
            origin: new THREE.Vector3(0, 0, 0),
            rate: 300,
            life: 2.5,
            emitterLife: 100, // 持续燃烧
            volecity: new THREE.Vector3(0, 8, 0),
            randomVelocity: {
                direction: new THREE.Vector3(0, 1, 0),
                coneAngle: 0.5, // 中等角度锥形
                speedMin: 5,
                speedMax: 12,
            },
            angle: 0,
            size: 1,
            shape: 'rect',
            shapeParams: { x: 3, y: 1, count: 20 }, // 小矩形底部
            material: material,
            maxCount: 1000,
        });

        // 向上的浮力（模拟热气上升）
        this.upwardForce = new GravityForceField(new THREE.Vector3(0, 3, 0));

        // 颜色变化：从红色到橙色到黄色再到透明
        this.colorTween = new Tween(
            [0, 0.8, 1.5, 2.5],
            [
                new THREE.Color(1, 0.1, 0.1),   // 深红色
                new THREE.Color(1, 0.5, 0.1),   // 橙色
                new THREE.Color(1, 1, 0.3),     // 黄色
                new THREE.Color(0.3, 0.3, 0.3)  // 烟雾灰色
            ],
            'color'
        );

        // 尺寸变化：从小变大
        this.sizeTween = new Tween(
            [0, 1, 2.5],
            [0.3, 1.5, 0.1],
            'size'
        );

        // 创建粒子系统
        this.particleSystem = new ParticleSystem(
            [this.emitter],
            [this.upwardForce],
            [this.colorTween, this.sizeTween],
            []
        );
    }

    protected createControls(folder: GUI): void {
        if (!this.emitter || !this.upwardForce) return;

        const controls = {
            intensity: 300,
            height: 8,
            width: 3,
            buoyancy: 3,
            spread: 0.5,
            particleLife: 2.5,
        };

        folder.add(controls, 'intensity', 50, 800)
            .name('火焰强度')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.rate = value;
                }
            });

        folder.add(controls, 'height', 3, 20)
            .name('初始速度')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.initialVelocity.y = value;
                    this.emitter.randomVelocity.speedMin = value * 0.6;
                    this.emitter.randomVelocity.speedMax = value * 1.5;
                }
            });

        folder.add(controls, 'width', 1, 10)
            .name('火焰底宽')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.shapeParams.x = value;
                }
            });

        folder.add(controls, 'buoyancy', 0, 10)
            .name('浮力强度')
            .onChange((value: number) => {
                if (this.upwardForce) {
                    this.upwardForce.gravity.y = value;
                }
            });

        folder.add(controls, 'spread', 0.1, 1.5)
            .name('扩散角度')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.randomVelocity.coneAngle = value;
                }
            });

        folder.add(controls, 'particleLife', 1, 5)
            .name('粒子生命')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.life = value;
                }
            });

        folder.open();
    }
}